﻿using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System;

namespace CDIO
{
    namespace POS
    {
        public struct Record
        {
            public ushort Card;
            public string date;
            public ushort Consume;
            public ushort Balance;
        }

        public class Pos
        {
            [DllImport("CDIO_Pos.dll", EntryPoint = "OpenCommPort")]
            private static extern int OpenCommPort(int Port, int BaudRate);

            [DllImport("CDIO_Pos.dll", EntryPoint = "BatchReadRecord")]
            private static extern int BatchReadRecord(int hPort, [In, Out] Record[] Records, int ArraySize);
            [DllImport("CDIO_Pos.dll", EntryPoint = "BatchReadRecord")]
            private static extern int BatchReadRecord(int hPort, [In, Out] byte[] Records, int ArraySize);


            [DllImport("CDIO_Pos.dll", EntryPoint = "CallClock")]
            private static extern bool CallPOS(int hPort, int clock_id);

            [DllImport("CDIO_Pos.dll", EntryPoint = "GetClockModel")]
            private static extern bool GetPOSModel(int hPort, out int Model, out double Fireware, out int cls);

            [DllImport("CDIO_Pos.dll", EntryPoint = "SetCmdVerify")]
            private static extern bool SetCmdVerify(bool Value);

            [DllImport("CDIO_Pos.dll", EntryPoint = "DisConnectClock")]
            private static extern bool DisConnectPOS(int hPort);

            [DllImport("CDIO_Pos.dll", EntryPoint = "SetBlackCard")]
            private static extern bool SetBlackCard(int hPort, byte[] CardNo);

            [DllImport("CDIO_Pos.dll", EntryPoint = "DeleteBlackCard")]
            private static extern bool DeleteBlackCard(int hPort, byte[] CardNo);

            private int hPort;
            public int Port;
            public int BaudRate;
            public int POS_id;
            public System.Threading.Mutex mutex;

            public Pos(int Port, int PosID, int BaudRate = 9600)
            {
                this.Port = Port;
                this.POS_id = PosID;
                this.BaudRate = BaudRate;
                this.mutex = new System.Threading.Mutex();
            }

            private bool CheckHandle
            {
                get
                {
                    if (hPort != 0 && hPort != -1)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            private bool OpenPort()
            {
                bool Result = false;
                int Model;
                double Fireware;
                int cls;
                if (CheckHandle)
                {
                    Result = true;
                }
                else
                {
                    hPort = OpenCommPort(Port, BaudRate);
                    SetCmdVerify(true);
                    if (CallPOS(hPort, POS_id))
                    {
                        if (GetPOSModel(hPort, out  Model, out Fireware, out cls))
                        {
                            Result = CheckHandle;
                        }
                    }
                }
                return Result;
            }

            private bool ClosePort()
            {
                bool Result = false;
                if (CheckHandle)
                {
                    DisConnectPOS(hPort);
                    Result = true;
                    hPort = 0;
                }
                return Result;
            }

            public bool IsConnected()
            {
                if (OpenPort())
                {
                    ClosePort();
                    return true;
                }
                return false;
            }

            public List<Record> ReadAllRecord(System.Windows.Forms.ListBox log)
            {
                List<Record> AllRecords = new List<Record>();
                bool flag;
                byte[] DataBuff = new byte[2000];
                int Count = 0;
                flag = true;
                if (OpenPort())
                {
                    while (flag)
                    {
                        int nLine = BatchReadRecord(hPort, DataBuff, 2000);

                        if (nLine > 0)
                        {
                            for (int k = 0; k < nLine; k++)
                            {
                                Record rd = new Record();
                                rd.Card = Convert.ToUInt16(Encoding.ASCII.GetString(DataBuff, k * 0x72, 20));
                                string date = Encoding.ASCII.GetString(DataBuff, 0x14, 20);
                                rd.date = date.Substring(0, 4) + "-" + date.Substring(4, 2) + "-" + date.Substring(6, 2) + " " + date.Substring(8, 2) + ":" + date.Substring(10, 2) + ":" + date.Substring(12, 2);
                                rd.Consume = BitConverter.ToUInt16(DataBuff, 0x3e);
                                rd.Balance = BitConverter.ToUInt16(DataBuff, 0x40);
                                AllRecords.Add(rd);
                                Count++;
                            }
                        }
                        else
                        {
                            flag = false;
                        }
                    }
                    if (Count > 0)
                    {
                        log.Items.Insert(0,System.DateTime.Now +"  "  + "读到记录数：" + Count);
                    }
                    else
                    {
                        log.Items.Insert(0,System.DateTime.Now +"  "  + "" + POS_id + "号机内没有记录");
                    }
                    ClosePort();
                    return AllRecords;
                }
                else
                {
                    log.Items.Insert(0,System.DateTime.Now +"  "  + "" + POS_id + "号设备连接失败." + "端口：COM" + Port);
                    return null;
                }
            }

            public bool SuspendCard(string CardNo, bool suspend = true)
            {
                bool result = false;
                if (OpenPort())
                {
                    byte[] CNbs = Encoding.Convert(
                        Encoding.Unicode,
                        Encoding.GetEncoding("GB2312"),
                        Encoding.Unicode.GetBytes(CardNo)
                        );
                    if (suspend)
                    {
                        result = SetBlackCard(hPort, CNbs);
                    }
                    else
                    {
                        result = DeleteBlackCard(hPort, CNbs);
                    }
                    ClosePort();
                }
                return result;
            }
        }

    }
}
